package com.hjw.dynamicdatasource.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.hjw.dynamicdatasource.config.DynamicDataSourceManager;
import com.hjw.dynamicdatasource.util.DatabaseMetadataUtil;
import com.hjw.dynamicdatasource.util.DynamicClassGenerator;
import com.hjw.dynamicdatasource.util.DynamicMapperFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.*;

import static com.baomidou.mybatisplus.generator.config.OutputFile.entity;

/**
 * 动态服务类，用于处理动态实体类的CRUD操作
 */
@Slf4j
@Service
public class DynamicService {

    @Autowired
    private DatabaseMetadataUtil databaseMetadataUtil;
    
    @Autowired
    private DynamicClassGenerator dynamicClassGenerator;
    
    @Autowired
    private DynamicMapperFactory dynamicMapperFactory;

    @Autowired
    private DynamicDataSourceManager dataSourceManager;

    
    /**
     * 获取数据库中所有表的结构信息
     * @param schema 数据库模式（可为空）
     * @return 表结构信息列表
     */
    public List<DatabaseMetadataUtil.TableInfo> getDatabaseTables(String schema) throws SQLException {
//        DataSource dataSource = dataSourceManager.getDataSource();
        return databaseMetadataUtil.getAllTables(dataSourceManager.getDataSource(), schema);
    }

    public void setCurrentDataSourceKey(String dataSourceKey){
        dynamicClassGenerator.setCurrentDataSourceKey(dataSourceKey);
    }
    
    /**
     * 为指定表动态生成实体类
     * @param tableName 表名
     * @param schema 数据库模式（可为空）
     * @return 生成的实体类
     */
    public Class<?> generateEntityClass(String tableName, String schema) throws Exception {
        // 获取表信息
        List<DatabaseMetadataUtil.TableInfo> tables = getDatabaseTables(schema);
        log.info("数据，{}",tables);
        tables.forEach(System.out::println);
        DatabaseMetadataUtil.TableInfo targetTable = null;
        
        for (DatabaseMetadataUtil.TableInfo table : tables) {
            if (table.getTableName().equalsIgnoreCase(tableName)) {
                targetTable = table;
                break;
            }
        }
        
        if (targetTable == null) {
            throw new IllegalArgumentException("表不存在: " + tableName);
        }
        
        // 生成实体类
        return dynamicClassGenerator.generateEntityClass(targetTable);
    }
    
    /**
     * 查询表中的所有数据
     * @param tableName 表名
     * @param schema 数据库模式（可为空）
     * @return 数据列表
     */
    @SuppressWarnings("unchecked")
    public List<Map<String, Object>> findAll(String tableName, String schema) throws Exception { 
         // 生成实体类 
         Class<?> entityClass = generateEntityClass(tableName, schema);

        // 创建Mapper
         BaseMapper<?> mapper = dynamicMapperFactory.createMapper(entityClass); 
         
         // 查询所有数据 
         List<?> entities = mapper.selectList(null);
         log.info("查询结果，{}",entities);
         
         // 转换为Map列表 - 使用已有的convertEntityToMap方法确保正确处理
         List<Map<String, Object>> result = new ArrayList<>(); 
         for (Object entity : entities) { 
             result.add(convertEntityToMap(entity)); 
         } 
         
         return result; 
     }
    
    /**
     * 根据ID查询数据
     * @param tableName 表名
     * @param id ID值
     * @param schema 数据库模式（可为空）
     * @return 数据Map
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> findById(String tableName, Object id, String schema) throws Exception {
        // 生成实体类
        Class<?> entityClass = generateEntityClass(tableName, schema);
        
        // 创建Mapper
        BaseMapper<?> mapper = dynamicMapperFactory.createMapper(entityClass);

        // 查询数据
        Object entity = mapper.selectById(new QueryWrapper<>().eq("id", id));
        
        // 转换为Map
        return entity != null ? convertEntityToMap(entity) : null;
    }
    
    /**
     * 插入数据
     * @param tableName 表名
     * @param data 数据Map
     * @param schema 数据库模式（可为空）
     * @return 插入结果
     */
    @SuppressWarnings("unchecked")
    public boolean insert(String tableName, Map<String, Object> data, String schema) throws Exception {
        // 生成实体类
        Class<?> entityClass = generateEntityClass(tableName, schema);
        
        // 创建实体实例
        Object entity = dynamicClassGenerator.createEntityInstance(entityClass, data);
        
        // 创建Mapper
        BaseMapper<?> mapper = dynamicMapperFactory.createMapper(entityClass);

        // 反射调用方法插入
        Method insert = BaseMapper.class.getMethod("insert", entity.getClass());
        insert.setAccessible(true);
        return  (int)insert.invoke(mapper, entity) > 0;
    }
    
    /**
     * 更新数据
     * @param tableName 表名
     * @param id ID值
     * @param data 数据Map
     * @param schema 数据库模式（可为空）
     * @return 更新结果
     */
    @SuppressWarnings("unchecked")
    public boolean update(String tableName, Object id, Map<String, Object> data, String schema) throws Exception {
        // 生成实体类
        Class<?> entityClass = generateEntityClass(tableName, schema);
        
        // 创建Mapper
        BaseMapper<?> mapper = dynamicMapperFactory.createMapper(entityClass);
        
        // 先查询现有数据
        Object entity = mapper.selectById(new QueryWrapper<>().eq("id", id));
        if (entity == null) {
            return false;
        }
        
        // 更新实体数据
        updateEntityFromMap(entity, data);
        Method updateById = BaseMapper.class.getMethod("updateById", entity.getClass());
        return  (int)updateById.invoke(mapper, entity) > 0;
        // 更新数据
    }
    
    /**
     * 删除数据
     * @param tableName 表名
     * @param id ID值
     * @param schema 数据库模式（可为空）
     * @return 删除结果
     */
    @SuppressWarnings("unchecked")
    public boolean delete(String tableName, Object id, String schema) throws Exception {
        // 生成实体类
        Class<?> entityClass = generateEntityClass(tableName, schema);
        
        // 创建Mapper
        BaseMapper<?> mapper = dynamicMapperFactory.createMapper(entityClass);

        Method deleteById = BaseMapper.class.getMethod("deleteById", entity.getClass());
        deleteById.setAccessible(true);
        return (int)deleteById.invoke(mapper, id) > 0;
    }
    
    /**
     * 执行动态SQL查询
     * @param sql SQL语句
     * @param params 参数Map
     * @param tableName 表名（用于获取实体类）
     * @param schema 数据库模式（可为空）
     * @return 查询结果列表
     */
    @SuppressWarnings("unchecked")
    public List<Map<String, Object>> executeSql(String sql, Map<String, Object> params, String tableName, String schema) throws Exception {
        // 生成实体类
        Class<?> entityClass = generateEntityClass(tableName, schema);
        
        // 执行查询
        List<?> entities = dynamicMapperFactory.executeQuery(sql, params, entityClass);
        
        // 转换为Map列表
        List<Map<String, Object>> result = new ArrayList<>();
        for (Object entity : entities) {
            result.add(convertEntityToMap(entity));
        }
        
        return result;
    }
    
    /**
     * 将实体对象转换为Map
     * @param entity 实体对象
     * @return Map
     */
    private Map<String, Object> convertEntityToMap(Object entity) {
        Map<String, Object> map = new HashMap<>();
        
        try {
            // 获取所有getter方法
            for (java.lang.reflect.Method method : entity.getClass().getMethods()) {
                String methodName = method.getName();
                
                // 判断是否为getter方法
                if (methodName.startsWith("get") && methodName.length() > 3 && method.getParameterCount() == 0) {
                    // 排除Object类的方法
                    if ("getClass".equals(methodName)) {
                        continue;
                    }
                    
                    // 生成字段名
                    String fieldName = methodName.substring(3);
                    fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1);
                    
                    // 调用getter方法获取值
                    Object value = method.invoke(entity);
                    map.put(fieldName, value);
                }
            }
        } catch (Exception e) {
            log.error("转换实体对象为Map失败", e);
            throw new RuntimeException("转换实体对象为Map失败", e);
        }
        
        return map;
    }
    
    /**
     * 从Map更新实体对象
     * @param entity 实体对象
     * @param data 数据Map
     */
    private void updateEntityFromMap(Object entity, Map<String, Object> data) {
        try {
            // 获取所有setter方法
            for (java.lang.reflect.Method method : entity.getClass().getMethods()) {
                String methodName = method.getName();
                
                // 判断是否为setter方法
                if (methodName.startsWith("set") && methodName.length() > 3 && method.getParameterCount() == 1) {
                    // 生成字段名
                    String fieldName = methodName.substring(3);
                    fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1);
                    
                    // 如果Map中包含该字段，则更新
                    if (data.containsKey(fieldName)) {
                        Object value = data.get(fieldName);
                        Class<?> paramType = method.getParameterTypes()[0];
                        
                        // 类型转换
                        Object convertedValue = dynamicClassGenerator.convertValue(value, paramType);
                        method.invoke(entity, convertedValue);
                    }
                }
            }
        } catch (Exception e) {
            log.error("从Map更新实体对象失败", e);
            throw new RuntimeException("从Map更新实体对象失败", e);
        }
    }
    
    /**
     * 清除所有缓存
     */
    public void clearCache() {
        dynamicClassGenerator.clearCache();
        dynamicMapperFactory.clearCache();
    }
}